﻿module Sustainalytics.Events.Admin {

    import Common = Sustainalytics.Common;
    import CommonAdmin = Sustainalytics.Common.Admin;

    export class EventsService implements IEventsService {

        private $q: ng.IQService;
        private $http: ng.IHttpService;
        private $location: ng.ILocationService;
        private staticObjectsAdmin: CommonAdmin.IStaticObjects;
        private notificationFactory: Common.INotificationFactory;
        

        // Ctor.
        constructor(
            $q: ng.IQService,
            $http: ng.IHttpService,
            $location: ng.ILocationService,
            notificationFactory: Common.INotificationFactory,
            staticObjectsAdmin: CommonAdmin.IStaticObjects) {

            this.$q = $q;
            this.$http = $http;
            this.$location = $location;
            this.staticObjectsAdmin = staticObjectsAdmin;
            this.notificationFactory = notificationFactory;
        }

        // show error message for a given error code
        private showError(err) {
            var ctx = this;
            if (err && err['errorCode'])
                ctx.notificationFactory.error('', ctx.staticObjectsAdmin.getMessageByInternalCode(err['errorCode']));
        }

        private eventsUrl(): string {
           return this.$location.protocol() + "://" + this.$location.host() + ":" + this.$location.port() + this.staticObjectsAdmin.eventsServiceBaseUrl
                + "/api/v1/events";
        }

        private eventUrl(id: string): string {
            return this.$location.protocol() + "://" + this.$location.host() + ":" + this.$location.port() + this.staticObjectsAdmin.eventsServiceBaseUrl
                + "/api/v1/events/" + id;
        }

        // get filtered list of events 
        public getEventsFiltered(filter: EventsFilter, skip: number, take: number, orderBy: string[], orderByAsc: boolean): ng.IPromise<EventDto[]> {

            var ctx = this;

            var options = new Sustainalytics.Common.ListOptions();
            options.skip = skip;
            options.take = take;
            options.orderBy = orderBy;
            options.orderAscending = orderByAsc;

            var promise = ctx.getEventsFilteredWithOptions(filter, options);

            return promise;
        }

        // get number of news
        public getEventsCount(filter: EventsFilter): ng.IPromise<number> {
            var ctx = this;

            var options = new Common.ListOptions();
            options.getCount = true;

            var promise = ctx.getEventsFilteredWithOptions(filter, options);

            return promise;
        }

        // get events paged
        public getEventsPaged(filter: EventsFilter, skip: number, take: number, orderBy: string[], orderByAsc: boolean): ng.IPromise<Common.PagedList<EventDto>> {
            var ctx = this;
            var itemsPromise = ctx.getEventsFiltered(filter, skip, take, orderBy, orderByAsc);
            var totalItemsCountPromise = ctx.getEventsCount(filter);

            var pagedListPromise = Common.PagedList.createPagedListFromPromises(ctx.$q, itemsPromise, skip, take, totalItemsCountPromise);

            return pagedListPromise;
        }

        // get filtered list of events
        public getEventsFilteredWithOptions(filter: EventsFilter, listOptions: Common.ListOptions): ng.IPromise<any> {
            var ctx = this;
            var def = this.$q.defer();
            var query :any = {};
            if (listOptions != undefined) {
                query =
                {
                    term: filter.term,
                    eventType: filter.type,
                    skip: listOptions.skip,
                    take: listOptions.take,
                    includeAllFields: listOptions.includeAllFields != undefined ? listOptions.includeAllFields : false,
                    getCount: listOptions.getCount,
                    orderBy: listOptions.orderBy != undefined ? listOptions.orderBy : "",
                    orderAscending: listOptions.orderAscending != undefined ? listOptions.orderAscending : false
                };
            }
            else {
                query =
                {
                    term: filter.term,
                    eventType: filter.type,
                }
            }

            var url = ctx.eventsUrl() + "?" + $.param(query);
            var promise = this.$http.get(url);
            promise.success(function (data: any) {
                if (!query.getCount) {
                    def.resolve(data.items);
                } else {
                    def.resolve(data.count);
                }

            }).error(function (err) { ctx.showError(err); def.reject(); })
            return def.promise;
        }

        public createEvent(dto: EventDto): ng.IHttpPromise<EventDto> {

            var ctx = this;

            return ctx.$http.post<EventDto>(ctx.eventsUrl(), dto);
        }

        public getEvent(eventId: string): ng.IPromise<EventDto> {
            var ctx = this;
            var def = this.$q.defer();

            var promise = ctx.$http.get(ctx.eventUrl(eventId));
            promise
                .success(function (data)
                {
                    def.resolve(data);
                })
                .error(function (err)
                {
                    ctx.showError(err);
                    def.reject();
                })
            return def.promise;
        }

        public updateEvent(dto: EventDto): ng.IHttpPromise<EventDto> {

            var ctx = this;

            return ctx.$http.put<EventDto>(ctx.eventsUrl(), dto);
        }

        // patch news - batch operations to be performed on News => HTTP PATCH
        public patchEvents(patchData: EventsPatch): ng.IPromise<{}> {
            var ctx = this;
            var def = this.$q.defer();
            var url = ctx.eventsUrl();
            var httpConfig: ng.IRequestConfig = { method: 'PATCH', url: url, data: patchData };
            var promise = this.$http(httpConfig);
            promise.success(function (data) { def.resolve(data); }).error(function (err) { ctx.showError(err); def.reject(); })
            return def.promise;
        }

    }


    // register service with News Angular module
    var mod = angular.module(eventsAdminModuleName);
    
    mod.service('EventsService',
        ['$q', '$http', '$location', 'notificationFactory', 'staticObjectsAdmin', EventsService]);
} 